home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / prftest.exe / PROFUNIT.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-04-14  |  14.7 KB  |  466 lines

  1. Unit ProfUnit;
  2.  
  3. {=====================================================================}
  4. {===== This code implements two standard Windows functions,      =====}
  5. {===== WritePrivateProfileString and GetPrivateProfileString.    =====}
  6. {===== In addition, a parsing function is included,              =====}
  7. {===== ParseProfileString, which is useful for parsing the       =====}
  8. {===== buffer returned by the Get... function.  This Pascal      =====}
  9. {===== implementation is an attempt to apply those functions     =====}
  10. {===== as well as the general notion of the ".INI" file to       =====}
  11. {===== DOS environment.  I've tried to make the functions        =====}
  12. {===== work exactly like their Windows API counterparts.  To     =====}
  13. {===== differentiate between the environments, my functions are  =====}
  14. {===== called WriteDOSProfileString and GetDOSProfileString.     =====}
  15. {=====                                                           =====}
  16. {===== Note that the arguments for all functions ARE CASE        =====}
  17. {===== SENSITIVE.  I will be adding code to resolve that as soon =====}
  18. {===== as I have the chance.  If there is any interest in this   =====}
  19. {===== code, I will upload updates as they are implemented.  If  =====}
  20. {===== there are any suggestions, please email to me on either:  =====}
  21. {=====                                                           =====}
  22. {=====          X.400:(c=us,a=attmail,d=id:mvabbc!wmpotvin)      =====}
  23. {=====   or                                                      =====}
  24. {=====          70540,120                                        =====}
  25. {=====                                                           =====}
  26. {===== Copyright(c) 1992 Wm Potvin II                            =====}
  27. {=====================================================================}
  28.  
  29. Interface
  30.  
  31. Uses
  32.   Dos;
  33.  
  34. Type
  35.   StrArray = array [1..80] of String[80];
  36.   ProfStr = String[255];
  37.   LinePtr = ^LineRecType;
  38.   LineRecType = Record
  39.     NextLine  : LinePtr;
  40.     LineField : ProfStr;
  41.   end;
  42.  
  43. Var
  44.   P1, P2, P3,
  45.   KeyUpDated,
  46.   AppUpDated,
  47.   KeyFound,
  48.   AppFound   : Boolean;
  49.   F          : Text;                     { File handle    }
  50.   Head       : LinePtr;                  { Head of List   }
  51.   Hold       : LinePtr;                  { Place Holder   }
  52.   Cur        : LinePtr;                  { Current Line   }
  53.   LineBuf    : ProfStr;                  { Input String   }
  54.   LineFieldIndex,
  55.   Count,
  56.   CountEnd,
  57.   Index,
  58.   BufIndex : Integer;
  59.  
  60. function WriteDOSProfileString(AppName,
  61.                                KeyName,
  62.                                Str: String;
  63.                                FileName: PathStr): Boolean;
  64.  
  65. function GetDOSProfileString(AppName,
  66.                              KeyName,
  67.                              Default: ProfStr;
  68.                              var RecvBuf: ProfStr;
  69.                              Size: Integer;
  70.                              FileName: PathStr): Integer;
  71.  
  72. function ParseProfileString(ProfileBuffer: ProfStr;
  73.                             var ReturnedArray: StrArray): Integer;
  74.  
  75. function ASCIIToUpper(StrBuffer: String): String;
  76.  
  77. Implementation
  78.  
  79. function WriteDOSProfileString(AppName,
  80.                                KeyName,
  81.                                Str: String;
  82.                                FileName: PathStr): Boolean;
  83.  
  84.  {***** Support Functions *****}
  85.  
  86.   function DeleteLine(DeleteStr: ProfStr): Boolean;
  87.   { deletes the line of the buffer containing DeleteStr. }
  88.   var
  89.     Count : Integer;
  90.   begin
  91.     DeleteLine := FALSE;
  92.     Hold := Head;
  93.     Cur := Head^.NextLine;
  94.     Count := 1;
  95.     while (Cur <> NIL) AND (Pos(DeleteStr, Cur^.LineField) = 0) do
  96.       begin
  97.         Hold := Cur;              { Save Current pointer }
  98.         Cur  := Cur^.NextLine;    { Advance to next line }
  99.       end;
  100.     if (Cur <> NIL) AND (Pos(DeleteStr, Cur^.LineField) <> 0) then
  101.       begin
  102.         Hold^.NextLine := Cur^.NextLine; {  skip current line }
  103.         FreeMem(Cur, Length(Cur^.LineField) + 5);
  104.         DeleteLine := TRUE;
  105.       end;
  106.   end;
  107.  
  108.   function DeleteAppName(DeleteAppStr: ProfStr): Boolean;
  109.   { deletes an entire App Section of the buffer containing DeleteAppStr. }
  110.   var
  111.     Count : Integer;
  112.   begin
  113.     DeleteAppName := FALSE;
  114.     Hold := Head;
  115.     Cur := Head^.NextLine;
  116.     while (Cur <> NIL) AND (Pos(DeleteAppStr, Cur^.LineField) < 2) do
  117.       begin
  118.         Hold := Cur;              { Save Current pointer }
  119.         Cur  := Cur^.NextLine;    { Advance to next line }
  120.       end;
  121.     if (Cur <> NIL) AND (Pos(DeleteAppStr, Cur^.LineField) <> 0) then
  122.       begin
  123.         while (Cur <> NIL) AND (Cur^.LineField <> ' ') do
  124.           begin
  125.             Hold^.NextLine := Cur^.NextLine; {  skip current line }
  126.             FreeMem(Cur, Length(Cur^.LineField) + 5);
  127.             Cur := Hold^.NextLine;
  128.           end;
  129.         DeleteAppName := TRUE;
  130.       end;
  131.   end;
  132.  
  133.   function InsertLine(NewStr: ProfStr): Boolean;
  134.   { inserts the line ProfStr after the last line under the AppName. }
  135.   var
  136.     NewLine: LinePtr;
  137.   begin
  138.     InsertLine := FALSE;
  139.     Hold := Head;
  140.     Cur  := Head^.NextLine;
  141.     while (Cur <> NIL) do
  142.       begin
  143.         Hold  := Cur;                      { Save current pointer }
  144.         Cur   := Cur^.NextLine;            { Advance to next line }
  145.         if (Hold^.LineField = '') AND      { if the old line is blank, }
  146.           (Cur^.LineField = '') then       { and the current line, too }
  147.             Cur := NIL;
  148.       end;
  149.     GetMem(NewLine, Length(NewStr) + 5);
  150.     Hold^.NextLine := NewLine;    { Change pointers to link }
  151.     NewLine^.NextLine := Cur;     {   in the new line       }
  152.     NewLine^.LineField := NewStr;
  153.     InsertLine := TRUE;
  154.   end;
  155.  
  156.   function InsertAppName(NewApp: ProfStr): Boolean;
  157.   var
  158.     P4, P5: Boolean;
  159.   begin
  160.     P4 := InsertLine('');
  161.     P5 := InsertLine(ConCat('[', AppName, ']'));
  162.   end;
  163.  
  164.   function LoadFile: Boolean;
  165.   {loads the file into a linked list }
  166.   begin
  167.     FileName := FExpand(FileName);
  168.     Assign(F, FileName);
  169.     {$I-}
  170.     Reset(F);
  171.     {I+} ;
  172.     if (IOResult = 0) then
  173.       begin
  174.         GetMem(Head, 4);
  175.         Head^.NextLine := NIL;              { Initialize Head }
  176.         Hold := Head;
  177.         while NOT Eof(F) do
  178.           begin
  179.             ReadLn(F, LineBuf);
  180.             GetMem(Cur, Length(LineBuf)+5); { Allocate Memory }
  181.             Hold^.NextLine := Cur;          { Set previous pointer }
  182.             Cur^.NextLine  := NIL;          { Cur goes at end of list }
  183.             Hold := Cur;                    { Save Current pointer }
  184.             Cur^.LineField := LineBuf;
  185.           end;
  186.         Close(F);
  187.         LoadFile := TRUE;
  188.       end
  189.     else
  190.       LoadFile := FALSE
  191.   end;
  192.  
  193.   function WriteFile: Boolean;
  194.   { traverse the list and write each line }
  195.   begin
  196.     FileName := FExpand(FileName);
  197.     Assign(F, FileName);
  198.     {$I-}
  199.     ReWrite(F);
  200.     {I+} ;
  201.     if (IOResult = 0) then
  202.       begin
  203.         Cur := Head^.NextLine;
  204.         while Cur <> NIL do
  205.           begin
  206.             WriteLn(F, Cur^.LineField);
  207.             Cur := Cur^.NextLine;
  208.           end;
  209.         Close(F);
  210.         WriteFile := TRUE;
  211.       end
  212.     else
  213.       WriteFile := FALSE;
  214.   end;
  215.  
  216.   {***** Begin Main Function *****}
  217.  
  218. begin
  219.   P1 := LoadFile;
  220.   if P1 then
  221.     begin
  222.       Cur := Head^.NextLine;
  223.       KeyUpDated := FALSE;
  224.       AppUpDated := FALSE;
  225.       while Cur <> NIL do
  226.         begin
  227.           if (KeyName = 'nil') then
  228.             begin
  229.               P3 := DeleteAppName(AppName);
  230.               P3 := WriteFile;
  231.               if P3 then
  232.                 WriteDOSProfileString := TRUE
  233.               else
  234.                 WriteDOSProfileString := FALSE;
  235.               Exit;
  236.             end
  237.           else
  238.           if Pos(AppName, Cur^.LineField) = 2 then
  239.             begin
  240.               while NOT AppUpdated do
  241.               begin
  242.               AppUpdated := TRUE;
  243.               Cur := Cur^.NextLine;
  244.               if Pos(KeyName, Cur^.LineField) = 1 then
  245.                 begin
  246.                   if (Str = 'nil') then
  247.                     begin
  248.                       P3 := DeleteLine(KeyName);
  249.                       P3 := WriteFile;
  250.                       if P3 then
  251.                         WriteDOSProfileString := TRUE
  252.                       else
  253.                         WriteDOSProfileString := FALSE;
  254.                       Exit;
  255.                     end
  256.                   else
  257.                     begin
  258.                       Cur^.LineField := ConCat(KeyName, '=', Str);
  259.                       P3 := WriteFile;
  260.                       if P3 then
  261.                         WriteDOSProfileString := TRUE
  262.                       else
  263.                         WriteDOSProfileString := FALSE;
  264.                       Exit;
  265.                     end;
  266.                 end
  267.               else
  268.                 if (Cur^.LineField = '') OR (Cur = NIL) then
  269.                   begin
  270.                     P3 := InsertLine(ConCat(KeyName, '=', Str));
  271.                     P3 := WriteFile;
  272.                     if P3 then
  273.                       WriteDOSProfileString := TRUE
  274.                     else
  275.                       WriteDOSProfileString := FALSE;
  276.                     Exit;
  277.                   end
  278.                 else
  279.                   AppUpdated := FALSE;
  280.             end;
  281.           end;
  282.           Cur := Cur^.NextLine;
  283.         end;
  284.       if (Cur = NIL) AND NOT AppUpdated then
  285.         begin
  286.           P3 := InsertAppName(AppName);
  287.           P3 := InsertLine(ConCat(KeyName, '=', Str));
  288.         end;
  289.       P2 := WriteFile;
  290.       if P2 then
  291.         WriteDOSProfileString := TRUE
  292.       else
  293.         WriteDOSProfileString := FALSE;
  294.     end
  295.   else
  296.     begin
  297.       {$I-}
  298.       ReWrite(F);
  299.       {$I+}
  300.       if IOResult = 0 then
  301.         begin
  302.           WriteLn(F);
  303.           WriteLn(F, '[', AppName, ']');
  304.           WriteLn(F, KeyName, '=', Str);
  305.           {$I-}
  306.           Close(F);
  307.           {$I+}
  308.           if IOResult = 0 then
  309.             WriteDOSProfileString := TRUE
  310.           else
  311.             WriteDOSProfileString := FALSE;
  312.         end
  313.       else
  314.         WriteDOSProfileString := FALSE;
  315.     end;
  316. end;
  317.  
  318. {***** End of function WriteDOSProfileString *****}
  319.  
  320. {***** Begin function GetDOSProfileString *****}
  321.  
  322. function GetDOSProfileString(AppName,
  323.                              KeyName,
  324.                              Default: ProfStr;
  325.                              var RecvBuf: ProfStr;
  326.                              Size: Integer;
  327.                              FileName: PathStr): Integer;
  328.  
  329.  {***** Support Functions *****}
  330.  
  331.   function LoadFile: Boolean;
  332.   {loads the file into a linked list }
  333.   begin
  334.     FileName := FExpand(FileName);
  335.     Assign(F, FileName);
  336.     {$I-}
  337.     Reset(F);
  338.     {I+} ;
  339.     if (IOResult = 0) then
  340.       begin
  341.         GetMem(Head, 4);
  342.         Head^.NextLine := NIL;              { Initialize Head }
  343.         Hold := Head;
  344.         while NOT Eof(F) do
  345.           begin
  346.             ReadLn(F, LineBuf);
  347.             GetMem(Cur, Length(LineBuf)+5); { Allocate Memory }
  348.             Hold^.NextLine := Cur;          { Set previous pointer }
  349.             Cur^.NextLine  := NIL;          { Cur goes at end of list }
  350.             Hold := Cur;                    { Save Current pointer }
  351.             Cur^.LineField := LineBuf;
  352.           end;
  353.         Close(F);
  354.         LoadFile := TRUE;
  355.       end
  356.     else
  357.       LoadFile := FALSE
  358.   end;
  359.  
  360. begin
  361.   P1 := LoadFile;
  362.   if P1 then
  363.     begin
  364.       Cur := Head^.NextLine;
  365.       AppFound := FALSE;
  366.       KeyFound := FALSE;
  367.       while Cur <> NIL do
  368.         begin
  369.           if (Pos(AppName, Cur^.LineField) <> 0) then
  370.             begin
  371.               AppFound := TRUE;
  372.               while AppFound do
  373.               begin
  374.               if (KeyName = 'nil') then
  375.                 begin
  376.                   Cur := Cur^.NextLine;
  377.                   while (Cur^.LineField <> '') AND (Cur <> NIL) do
  378.                     begin
  379.                       LineFieldIndex := 1;
  380.                       BufIndex := 1;
  381.                       LineFieldIndex := Pos('=', Cur^.LineField);
  382.                       if KeyFound then
  383.                         RecvBuf := ConCat(RecvBuf, Copy(Cur^.LineField, 1, LineFieldIndex - 1))
  384.                       else
  385.                         RecvBuf := Copy(Cur^.LineField, 1, LineFieldIndex - 1);
  386.                       Cur := Cur^.NextLine;
  387.                       if (Cur <> NIL) then
  388.                         RecvBuf := ConCat(RecvBuf, ',');
  389.                       KeyFound := TRUE;
  390.                     end;
  391.                   Cur := NIL;
  392.                 end;
  393.               if (KeyName = Copy(Cur^.LineField, 1, Pos('=', Cur^.LineField)-1))
  394.                 AND NOT KeyFound then
  395.                 begin
  396.                   LineFieldIndex := 1;
  397.                   BufIndex := 1;
  398.                   while Cur^.LineField[LineFieldIndex] <> '=' do
  399.                     inc(LineFieldIndex);
  400.                   CountEnd :=(Length(Cur^.LineField) - LineFieldIndex);
  401.                   RecvBuf := Copy(Cur^.LineField, LineFieldIndex + 1, CountEnd);
  402.                   if RecvBuf = ' ' then RecvBuf := Default;
  403.                   KeyFound := TRUE;
  404.                 end
  405.               else
  406.                 if (Cur <> NIL) then
  407.                   begin
  408.                     AppUpdated := FALSE;
  409.                     Cur := Cur^.NextLine;
  410.                   end
  411.                 else
  412.                   AppFound := FALSE;
  413.               end;
  414.             end;
  415.           if Cur <> NIL then Cur := Cur^.NextLine;
  416.         end;
  417.       if NOT KeyFound then RecvBuf := Default;
  418.     end;
  419.   GetDOSProfileString := Length(RecvBuf);
  420. end;
  421.  
  422.  {***** End of function GetDOSProfileString *****}
  423.  
  424.  {***** Begin function ParseProfileString *****}
  425.  
  426. function ParseProfileString(ProfileBuffer: ProfStr;
  427.                             var ReturnedArray: StrArray): Integer;
  428. var
  429.   Count, Start, NumBytes: Integer;
  430.   Done: Boolean;
  431. begin
  432.   Start := 1;
  433.   Count := 0;
  434.   Done := FALSE;
  435.   while NOT Done do
  436.     begin
  437.       NumBytes := Pos(',', ProfileBuffer);
  438.       if NumBytes = 0 then
  439.         begin
  440.           NumBytes := Length(ProfileBuffer);
  441.           Done := TRUE;
  442.         end;
  443.       if NOT Done then
  444.         ReturnedArray[Count] := Copy(ProfileBuffer, 1, NumBytes - 1)
  445.       else
  446.         ReturnedArray[Count] := Copy(ProfileBuffer, 1, NumBytes);
  447.       ProfileBuffer := Copy(ProfileBuffer, NumBytes + 1, Length(ProfileBuffer) - NumBytes);
  448.       inc(Count);
  449.     end;
  450.   ParseProfileString := Count;
  451. end;
  452.  
  453.  {***** End of function ParseProfileString *****}
  454.  
  455. function ASCIIToUpper(StrBuffer: String): String;
  456. var
  457.   Index: Integer;
  458. begin
  459.   for Index := 1 to Length(StrBuffer) do
  460.     begin
  461.       StrBuffer[Index] := UpCase(StrBuffer[Index]);
  462.     end;
  463. end;
  464.  
  465.  
  466. end.